(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define('simple-hotkeys', ["jquery",
      "simple-module"], function ($, SimpleModule) {
      return (root.returnExportsGlobal = factory($, SimpleModule));
    });
  } else if (typeof exports === 'object') {
    // Node. Does not work with strict CommonJS, but
    // only CommonJS-like enviroments that support module.exports,
    // like Node.
    module.exports = factory(require("jquery"),
        require("simple-module"));
  } else {
    root.simple = root.simple || {};
    root.simple['hotkeys'] = factory(jQuery,
        SimpleModule);
  }
}(this, function ($, SimpleModule) {

  var Hotkeys, hotkeys,
      __hasProp = {}.hasOwnProperty,
      __extends = function (child, parent) {
        for (var key in parent) {
          if (__hasProp.call(parent, key)) {
            child[key] = parent[key];
          }
        }

        function ctor() {
          this.constructor = child;
        }

        ctor.prototype = parent.prototype;
        child.prototype = new ctor();
        child.__super__ = parent.prototype;
        return child;
      };

  Hotkeys = (function (_super) {
    __extends(Hotkeys, _super);

    function Hotkeys() {
      return Hotkeys.__super__.constructor.apply(this, arguments);
    }

    Hotkeys.count = 0;

    Hotkeys.keyNameMap = {
      8: "Backspace",
      9: "Tab",
      13: "Enter",
      16: "Shift",
      17: "Control",
      18: "Alt",
      19: "Pause",
      20: "CapsLock",
      27: "Esc",
      32: "Spacebar",
      33: "PageUp",
      34: "PageDown",
      35: "End",
      36: "Home",
      37: "Left",
      38: "Up",
      39: "Right",
      40: "Down",
      45: "Insert",
      46: "Del",
      91: "Meta",
      93: "Meta",
      48: "0",
      49: "1",
      50: "2",
      51: "3",
      52: "4",
      53: "5",
      54: "6",
      55: "7",
      56: "8",
      57: "9",
      65: "A",
      66: "B",
      67: "C",
      68: "D",
      69: "E",
      70: "F",
      71: "G",
      72: "H",
      73: "I",
      74: "J",
      75: "K",
      76: "L",
      77: "M",
      78: "N",
      79: "O",
      80: "P",
      81: "Q",
      82: "R",
      83: "S",
      84: "T",
      85: "U",
      86: "V",
      87: "W",
      88: "X",
      89: "Y",
      90: "Z",
      96: "0",
      97: "1",
      98: "2",
      99: "3",
      100: "4",
      101: "5",
      102: "6",
      103: "7",
      104: "8",
      105: "9",
      106: "Multiply",
      107: "Add",
      109: "Subtract",
      110: "Decimal",
      111: "Divide",
      112: "F1",
      113: "F2",
      114: "F3",
      115: "F4",
      116: "F5",
      117: "F6",
      118: "F7",
      119: "F8",
      120: "F9",
      121: "F10",
      122: "F11",
      123: "F12",
      124: "F13",
      125: "F14",
      126: "F15",
      127: "F16",
      128: "F17",
      129: "F18",
      130: "F19",
      131: "F20",
      132: "F21",
      133: "F22",
      134: "F23",
      135: "F24",
      59: ";",
      61: "=",
      186: ";",
      187: "=",
      188: ",",
      190: ".",
      191: "/",
      192: "`",
      219: "[",
      220: "\\",
      221: "]",
      222: "'"
    };

    Hotkeys.aliases = {
      "escape": "esc",
      "delete": "del",
      "return": "enter",
      "ctrl": "control",
      "space": "spacebar",
      "ins": "insert",
      "cmd": "meta",
      "command": "meta",
      "wins": "meta",
      "windows": "meta"
    };

    Hotkeys.normalize = function (shortcut) {
      var i, key, keyname, keys, _i, _len;
      keys = shortcut.toLowerCase().replace(/\s+/gi, "").split("+");
      for (i = _i = 0, _len = keys.length; _i < _len; i = ++_i) {
        key = keys[i];
        keys[i] = this.aliases[key] || key;
      }
      keyname = keys.pop();
      keys.sort().push(keyname);
      return keys.join("_");
    };

    Hotkeys.prototype.opts = {
      el: document
    };

    Hotkeys.prototype._init = function () {
      this.id = ++this.constructor.count;
      this._map = {};
      this._delegate = typeof this.opts.el === "string" ? document
          : this.opts.el;
      return $(this._delegate).on("keydown.simple-hotkeys-" + this.id,
          this.opts.el, (function (_this) {
            return function (e) {
              var _ref;
              return (_ref = _this._getHander(e)) != null ? _ref.call(_this, e)
                  : void 0;
            };
          })(this));
    };

    Hotkeys.prototype._getHander = function (e) {
      var keyname, shortcut;
      if (!(keyname = this.constructor.keyNameMap[e.which])) {
        return;
      }
      shortcut = "";
      if (e.altKey) {
        shortcut += "alt_";
      }
      if (e.ctrlKey) {
        shortcut += "control_";
      }
      if (e.metaKey) {
        shortcut += "meta_";
      }
      if (e.shiftKey) {
        shortcut += "shift_";
      }
      shortcut += keyname.toLowerCase();
      return this._map[shortcut];
    };

    Hotkeys.prototype.respondTo = function (subject) {
      if (typeof subject === 'string') {
        return this._map[this.constructor.normalize(subject)] != null;
      } else {
        return this._getHander(subject) != null;
      }
    };

    Hotkeys.prototype.add = function (shortcut, handler) {
      this._map[this.constructor.normalize(shortcut)] = handler;
      return this;
    };

    Hotkeys.prototype.remove = function (shortcut) {
      delete this._map[this.constructor.normalize(shortcut)];
      return this;
    };

    Hotkeys.prototype.destroy = function () {
      $(this._delegate).off(".simple-hotkeys-" + this.id);
      this._map = {};
      return this;
    };

    return Hotkeys;

  })(SimpleModule);

  hotkeys = function (opts) {
    return new Hotkeys(opts);
  };

  return hotkeys;

}));

